package com.fruit.auth.dao.impl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.jdbc.Work;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import com.fruit.auth.dao.UserRoleDao;
import com.fruit.auth.model.Role;
import com.fruit.auth.model.User;
import com.fruit.auth.model.UserRole;
import com.fruit.dao.impl.BaseDaoImpl;

@Repository("userRoleDao")
public class UserRoleDaoImpl extends BaseDaoImpl<UserRole> implements UserRoleDao
{

	public void saveUserRole(UserRole userRole)
	{
		String hql="select count(*) from UserRole ur where ur.user=? and ur.role=?";
		long count=(long)findUniqueResultByHql(hql, userRole.getUser(),userRole.getRole());
		if(count==0)
		{
			saveEntity(userRole);
		}
	}
	
	public void saveUserRoles(final User user,final List<Serializable> roleIds)
	{
		final String sql="insert into AUTH_USER_ROLE (AUTH_USER_id,AUTH_ROLE_id) values(?,?)";
		getSession().doWork(new Work()
		{
			
			@Override
			public void execute(Connection connection) throws SQLException
			{
				connection.setAutoCommit(false);
				PreparedStatement stat=connection.prepareStatement(sql);
				for(int i=0;i<roleIds.size();i++)
				{
					stat.setInt(1, user.getId());
					stat.setInt(2,	(int) roleIds.get(i));
					stat.addBatch();
				}
				stat.executeBatch();
				connection.commit();
			}
		});
	}
	
	public UserRole findUserRole(User user,Role role)
	{
		String hql="from UserRole ur left join fetch ur.user left join fetch ur.role where ur.user.id=? and ur.role.id=?";
		return (UserRole) findUniqueResultByHql(hql, user.getId(),role.getId());
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Role> findUserRoles(User user)
	{
		String hql="select ur.role from UserRole ur where ur.user.id=?0";
		return getSession().createQuery(hql).setParameter("0", user.getId()).list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Serializable> findUserRoleIds(User user)
	{
		String hql="select ur.role.id from UserRole ur where ur.user.id=?0";
		return getSession().createQuery(hql).setParameter("0", user.getId()).list();
	}

	public void updateUserRoles(User user,List<Serializable> roleIds)
	{
		String hql;
		//判断角色rIds是否为空，如果为空则说明未分配任何角色，则清空数据库该用户所有已有角色关系
		if(CollectionUtils.isEmpty(roleIds))
		{
			hql="delete from UserRole ur where ur.user.id=?";
			batchEntityByHql(hql, user.getId());
		}
		else
		{
			List<Serializable> db_roleIds=findUserRoleIds(user);
			if(CollectionUtils.isEmpty(db_roleIds))
			{
				saveUserRoles(user, roleIds);
			}
			else
			{
				final StringBuilder sb=new StringBuilder();
				//数据库里该用户已经存在的角色不全部包含页面分配的角色，说明有新角色分配，要插入
				if(!db_roleIds.containsAll(roleIds))
				{
					List<Serializable> newRoleIds=new ArrayList<Serializable>();
					for(Serializable roleId:roleIds)
					{
						if(!db_roleIds.contains(roleId))
						{
							newRoleIds.add(roleId);
						}
					}
					saveUserRoles(user, newRoleIds);
					
				}
				
				//该用户在页面分配的角色不全部包含数据库中所有已有角色，即用户在页面上删除了该用户的某些角色
				if(!roleIds.containsAll(db_roleIds))
				{
					sb.append("delete from AUTH_USER_ROLE where AUTH_USER_id=? and AUTH_ROLE_id in(");
					for(Serializable db_roleId:db_roleIds)
					{
						if(!roleIds.contains(db_roleId))
						{
							sb.append(db_roleId).append(",");
						}
					}
					sb.deleteCharAt(sb.length()-1).append(")");
					getSession().doWork(new Work()
					{
						
						@Override
						public void execute(Connection connection) throws SQLException
						{
							connection.setAutoCommit(false);
							PreparedStatement stat=connection.prepareStatement(sb.toString());
							stat.executeUpdate();
							stat.close();
						}
					});
				}
			}
		}
	}
	
	public void unAuthRoleUsers(Role role)
	{
		String hql="delete from UserRole ur where ur.role=?";
		batchEntityByHql(hql, role);
	}
	//解除多个角色与用户的关系
	public void unAuthRolesUsers(String roleIdsStr)
	{
		StringBuilder deleteRoleUserSql=new StringBuilder();
		deleteRoleUserSql.append("delete from AUTH_USER_ROLE where AUTH_ROLE_id in(");
		deleteRoleUserSql.append(roleIdsStr).append(")");
		executeUpdateSql(deleteRoleUserSql.toString());
	}
	
	public void unAuthUserRoles(User user)
	{
		String hql="delete from UserRole ur where ur.user.id=?";
		batchEntityByHql(hql, user.getId());
	}
	
	//解除多个用户与角色的关系
	public void unAuthUsersRoles(String userIdsStr)
	{
		StringBuilder deleteUserRoleSql=new StringBuilder();
		deleteUserRoleSql.append("delete from AUTH_USER_ROLE where AUTH_USER_id in(");
		deleteUserRoleSql.append(userIdsStr).append(")");
		executeUpdateSql(deleteUserRoleSql.toString());
	}
}
